import fs from 'fs-extra';
import path from "path";
import { CopyXsdkLibrary, GradleBuild, ModifyGradle, recordApk, UploadApk } from './AndroidBuildUtil.js';
import { CmdOption } from '../../CmdOption.js';
import { toolchain } from '../../toolchain.js';
import { safeCopyFile } from '../../tools/vendor.js';
import { TaskResult } from '../../common/tasks/BastTask.js';
import { PrebuildAppData, PreBuildAppTask } from '../../common/tasks/PreBuildAppTask.js';
import ini from 'ini';
import { IBuildAppResult } from '../../typings.js';


/**
 * 导出unity的gradle工程
 */
class ExportUnityGradle {
    constructor(private cmdOption: CmdOption, private exportproj: string,
        private defines: string,
        private versionCode: string) { }
    async export() {
        await this.setEditorPrefs();

        const channelCfg = toolchain.params.channelCfg;

        await fs.remove(this.exportproj);
        let outVersion = "";
        let bundleVersion = toolchain.params.channelCfg.bundleVersion!;
        if (!toolchain.params.channelCfg.bundleVersion) {
            bundleVersion = toolchain.params.version + '.' + this.versionCode;
            outVersion = bundleVersion;
        } else {
            outVersion = toolchain.params.channelCfg.bundleVersion + "(" + this.versionCode + ")";
        }
        const params = ['-batchmode', '-projectPath', toolchain.params.workSpacePath, '-executeMethod', 'BuildCommand.ExportAndroidProj',
            '-defines', this.defines, '-bundleVersion', bundleVersion, '-versionCode', this.versionCode, '-bundleId', channelCfg.bundleId, '-productName', channelCfg.productName.replace(/ /g, '%20'),
            '-targetSdkVersion', channelCfg.targetSdkVersion!, '-androidsdkroot', toolchain.params.androidSdkRoot, '-androidndkroot', toolchain.params.androidNdkRoot, '-quit'];
        await toolchain.unity.runUnityCommand(this.cmdOption, params, 'APK');

        // 兼容gradle8
        const gradles = [
            { path: path.join(this.exportproj, 'launcher/build.gradle'), pkgname: channelCfg.bundleId },
            { path: path.join(this.exportproj, 'unityLibrary/build.gradle'), pkgname: "com.unity3d.player" }
        ];
        for (let gradle of gradles) {
            if (fs.existsSync(gradle.path)) {
                const con = await fs.readFile(gradle.path, "utf8");
                if (!con.includes("namespace")) {
                    await fs.writeFile(gradle.path, con + `
                    android {
                        if (gradle.gradleVersion.split('\\\\.')[0].toInteger() >= 7) {
                            namespace "${gradle.pkgname}"
                        }
                    }
                    `, 'utf8');
                }
            }
        }

        // 兼容unity2022, 修改settings.gradle
        const settingsPath = path.join(this.exportproj, 'settings.gradle');
        if (fs.existsSync(settingsPath)) {
            await fs.writeFile(settingsPath, "include ':launcher', ':unityLibrary' \n", 'utf8');
        }

        return outVersion;
    }

    private async setEditorPrefs() {
        if (!toolchain.params.needsetEditorPrefs) return;

        console.log('setEditorPrefs');

        const params = ['-batchmode', '-projectPath', toolchain.params.workSpacePath,
            '-executeMethod', 'BuildCommand.SetEditorPrefs', '-androidsdkroot', toolchain.params.androidSdkRoot, '-androidndkroot', toolchain.params.androidNdkRoot, '-quit'];
        await toolchain.unity.runUnityCommand(this.cmdOption, params, 'Prefs');
    }
}

/**
 * 修复unity2019版本在api>30的系统上播放声音异常的bug
 */
class FixUnity2019SoundBug {
    constructor(private cmdOption: CmdOption, private xsdkPath: string, private exportproj: string) { }
    async fix() {
        let unityJarPath = path.join(this.xsdkPath, '../tools/unity_fix_jar', toolchain.params.unityVer, 'unity-classes.jar');
        const dst = path.join(this.exportproj, 'unityLibrary/libs/unity-classes.jar');
        if (fs.existsSync(unityJarPath)) {
            console.log("copy " + unityJarPath + " to " + dst);
            await safeCopyFile(unityJarPath, dst);
        }
    }
}

export class AndroidBuildUnity {
    static async run(cmdOption: CmdOption): Promise<TaskResult<IBuildAppResult>> {
        const prebuildResult = toolchain.taskHelper.getResult<PrebuildAppData>(PreBuildAppTask.name);

        const c = toolchain.params.channelCfg;
        let exportproj = path.join(toolchain.params.workSpacePath, '../export');
        const xsdkPath = path.join(cmdOption.oldToolsRoot, 'sdk/android/xsdk');

        // 导出unity的gradle工程
        const version = await new ExportUnityGradle(cmdOption, exportproj, prebuildResult!.data!.defines, prebuildResult!.data!.versionCode).export();

        // 如果是unity2019.4.40f1版本，替换unity_class.jar(该版本在androidapi>30的系统上无法播放声音)
        await new FixUnity2019SoundBug(cmdOption, xsdkPath, exportproj).fix();

        // 将xsdkLibrary复制到unity的gradle工程中
        let changeXSdkPackage = await new CopyXsdkLibrary(xsdkPath, toolchain.params, exportproj, cmdOption).copy();

        // 将xsdkLibrary嵌入到unity的gradle工程中
        let gradleProperties = await new ModifyGradle(exportproj, changeXSdkPackage, c.bundleId, 'launcher').insert();

        // 构建unity的gradle工程，生成apk/aab
        await new GradleBuild(exportproj, xsdkPath, gradleProperties, 'unityLibrary').build(c.apk!.endsWith('.aab'));

        // 将构建好的apk/aab放到 hudson下 供内网下载
        const apkName = await new UploadApk(toolchain.params, exportproj, version, 'launcher').upload();

        // 记录该次构建信息到项目的build/apks.txt
        await recordApk(apkName);

        // 修改最低版本号
        if (cmdOption.setMinApp) {
            const uploadPath = path.join(toolchain.params.uploadPath, toolchain.unity.getAssetsDir());
            await fs.ensureDir(uploadPath);
            await fs.writeFile(path.join(uploadPath, 'minappver.txt'), version, 'utf-8');
        }
        return { success: true, errorCode: 0, data: { apkName, version } };
    }
}